using System;
using System.Collections.Generic;

namespace NFreeMarker.Cache
{
    /**
     * Soft cache storage is a cache storage that uses {@link SoftReference} 
     * objects to hold the objects it was passed, therefore allows the garbage
     * collector to purge the cache when it determines that it wants to free up
     * memory.
     * This class is thread-safe to the extent that its underlying map is. The 
     * default implementation uses a concurrent map on Java 5 and above, so it is
     * thread-safe in that case.
     * @author Attila Szegedi
     * @version $Id: SoftCacheStorage.java,v 1.4 2003/09/22 20:47:03 ddekany Exp $
     *
     */
    public class SoftCacheStorage : IConcurrentCacheStorage
    {
        //private static readonly Method atomicRemove = getAtomicRemoveMethod();
        
        //private readonly ReferenceQueue queue = new ReferenceQueue();
        private readonly IDictionary<object, object> _map;
        private readonly bool _concurrent;
        
        public SoftCacheStorage()
            : this(ConcurrentMapFactory.CreateMap())
        {
        }
        
        public bool IsConcurrent() {
            return _concurrent;
        }
        
        public SoftCacheStorage(IDictionary<object, object> backingMap) {
            _map = backingMap;
            _concurrent = ConcurrentMapFactory.IsConcurrent(_map);
        }
        
        public object Get(object key)
        {
            // TODO: Implement SoftCacheStorage.Get()
            //ProcessQueue();
            //Reference ref = (Reference)_map.get(key);
            //return ref == null ? null : ref.get();

            return null;
        }

        public void Put(object key, object value) {
            // TODO: Implement SoftCacheStorage.Put()
            //ProcessQueue();
            //_map.Add(key, new SoftValueReference(key, value, queue));
        }

        public void Remove(object key) {
            ProcessQueue();
            _map.Remove(key);
        }

        public void Clear() {
            _map.Clear();
            ProcessQueue();
        }

        private void ProcessQueue() {
            // TODO
            //for (; ; )
            //{
            //    SoftValueReference ref = (SoftValueReference)queue.poll();
            //    if(ref == null) {
            //        return;
            //    }
            //    object key = ref.getKey();
            //    if(_concurrent) {
            //        try {
            //            atomicRemove.invoke(_map, new object[] { key, ref });
            //        }
            //        catch(IllegalAccessException e) {
            //            throw new UndeclaredThrowableException(e);
            //        }
            //        catch(InvocationTargetException e) {
            //            throw new UndeclaredThrowableException(e);
            //        }
            //    }
            //    else if(_map.get(key) == ref) {
            //        _map.remove(key);
            //    }
            //}
        }

        //private class SoftValueReference : SoftReference {
        //    private readonly object key;

        //    SoftValueReference(object key, object value, ReferenceQueue queue) {
        //        super(value, queue);
        //        this.key = key;
        //    }

        //    object GetKey() {
        //        return key;
        //    }
        //}
        
        //private static Method GetAtomicRemoveMethod() {
        //    try {
        //        return Class.forName("java.util.concurrent.ConcurrentMap").getMethod("remove", new Class[] { object.class, object.class });
        //    }
        //    catch(ClassNotFoundException e) {
        //        return null;
        //    }
        //    catch(NoSuchMethodException e) {
        //        throw new UndeclaredThrowableException(e);
        //    }
        //}
    }
}